#ifndef numuCCMultiPiSelection_h
#define numuCCMultiPiSelection_h

#include "SelectionBase.hxx"
#include "Parameters.hxx"

class numuCCMultiPiSelection: public SelectionBase{

    public:
        numuCCMultiPiSelection(bool forceBreak=true);
        virtual ~numuCCMultiPiSelection(){}

        void DefineSteps();
        inline AnaBoxB* MakeBox();
        bool FillEventSummary(const AnaBoxB& box, AnaEventB& event, Int_t allCutsPassed[]);
        nd280Samples::SampleEnum GetSampleEnum(){return nd280Samples::kFGD1NuMuCC0Pi;}

};

class AnaBoxCCMultiPi: public AnaBoxB{

    public:
        AnaBoxCCMultiPi(){
            nPositivePionTPCtracks = 0;
            nNegativePionTPCtracks = 0;
            nMichelElectrons = 0;
            nIsoFGDPiontracks = 0;
            nPosPi0TPCtracks = 0;
            nElPi0TPCtracks = 0;
            nIsoFGDElPi0tracks = 0;
            nTPC1tracks = 0;
            nPosPions = 0;
            nOtherPions = 0;
        }

        virtual ~AnaBoxCCMultiPi(){}

        // positive  TPC pion candidates 
        AnaTrackB* PositivePionTPCtracks[100];
        int nPositivePionTPCtracks;

        // negative TPC pion candidates 
        AnaTrackB* NegativePionTPCtracks[100];
        int nNegativePionTPCtracks;

        //  Michel Electron candidates 
        AnaFgdTimeBinB* MichelElectrons[100];
        int nMichelElectrons;

        // IsoFGD Pion candidates 
        AnaTrackB* IsoFGDPiontracks[100];
        int nIsoFGDPiontracks;

        // Electrons and positrons from Pio in the TPC
        AnaTrackB* PosPi0TPCtracks[100];
        AnaTrackB* ElPi0TPCtracks[100];
        int nPosPi0TPCtracks;
        int nElPi0TPCtracks;

        // IsoFGD electron and positron candidates 
        AnaTrackB* IsoFGDElPi0tracks[100];
        int nIsoFGDElPi0tracks;

        // Tracks with component in TPC1
        AnaTrackB* TPC1tracks[100];
        int nTPC1tracks;

        int nPosPions;
        int nOtherPions;

};

namespace numuCCMultiPiUtils{
        //From NumuCCBANFF Standard Actions.
        void FindTPCPions(const AnaEventB& event, AnaBoxB& box, SubDetId::SubDetEnum det, bool useOldSecondaryPID);
        void FindIsoFGDPions(const AnaEventB& event, AnaBoxCCMultiPi& ccmultipibox, SubDetId::SubDetEnum det);
        void FindIsoFGDElPi0(const AnaEventB& event, AnaBoxCCMultiPi& ccmultipibox, SubDetId::SubDetEnum det);
        void FindMEPions(const AnaEventB& event, AnaBoxCCMultiPi& ccmultipibox, SubDetId::SubDetEnum det, bool prod5Cut = 0);

        //From NumuCCBANFF Analysis Utils.
        bool TPCpionSelection(AnaTrackB *track);
        bool TPCElPi0Selection(AnaTrackB *track);
        bool FGDpionSelection(AnaTrackB *track, SubDetId::SubDetEnum det);
        bool FGDElPi0Selection(AnaTrackB *track, AnaBoxCCMultiPi& ccmultipibox, SubDetId::SubDetEnum det);
}


inline AnaBoxB* numuCCMultiPiSelection::MakeBox() {return new AnaBoxCCMultiPi();}

class NoPionCut: public StepBase{  
    public:
        using StepBase::Apply;
        bool Apply(const AnaEventB& event, AnaBoxB& box) const;
        StepBase* MakeClone(){return new NoPionCut();}
};

class OnePionCut: public StepBase{  
    public:
        using StepBase::Apply;
        bool Apply(const AnaEventB& event, AnaBoxB& box) const;
        StepBase* MakeClone(){return new OnePionCut();}
};

class OthersCut: public StepBase{  
    public:
        using StepBase::Apply;
        bool Apply(const AnaEventB& event, AnaBoxB& box) const;
        StepBase* MakeClone(){return new OthersCut();}
};

class FillSummaryAction_numuCCMultiPi: public StepBase{
    public:
        using StepBase::Apply;
        bool Apply(const AnaEventB& event, AnaBoxB& box) const;  
        StepBase* MakeClone(){return new FillSummaryAction_numuCCMultiPi();}
};

class FindPionsAction: public StepBase{
    public:
        using StepBase::Apply;
        FindPionsAction(){
            useTPCPions = (bool)ND::params().GetParameterI("psycheSelections.numuCCMultiPi.UseTPCPions");
            useME = (bool)ND::params().GetParameterI("psycheSelections.numuCCMultiPi.UseME");
            useFGDPions = (bool)ND::params().GetParameterI("psycheSelections.numuCCMultiPi.UseFGDPions");
            useOldSecondaryPID = (bool) ND::params().GetParameterI("psycheSelections.numuCCMultiPi.OldSecondaryPID");
            prod5Cut = (bool)ND::params().GetParameterI("psycheSelections.numuCCMultiPi.Prod5Cuts");
        }
        bool useTPCPions;
        bool useME;
        bool useFGDPions;
        bool useOldSecondaryPID;
        bool prod5Cut;

        bool Apply(const AnaEventB& event, AnaBoxB& box) const;  
        StepBase* MakeClone(){return new FindPionsAction();}
};

class FindTPC1TracksAction: public StepBase{

    public:
        using StepBase::Apply;
        bool Apply(const AnaEventB& event, AnaBoxB& box) const;  
        StepBase* MakeClone(){return new FindTPC1TracksAction();}
};

#endif
